import json
import re

from flask import request, jsonify, Blueprint, current_app, render_template, app, send_from_directory, session
from datetime import datetime
import os

from config.loggingConf import FlaskLogger
from match import log_file_reconciliation
from service.AhfdHandle import process_anhuifeidon_reconciliation
from service.AhhxHandle import process_anhuihonxing_reconciliation
from service.AhljHandle import process_anhuiluoji_reconciliation
from service.AhshHandle import process_anhuishuanghe_reconciliation
from service.AyHandle import process_anyang_reconciliation
from service.BtsxHandle import process_baotoushixin_reconciliation
from service.BzHandle import process_binzhou_reconciliation
from service.CcytHandle import process_changchunyintai_reconciliation
from service.CdjyHandle import process_chengdujianyang_reconciliation
from service.CdsrHandle import process_chendushuangrui_reconciliation
from service.CqdgHandle import process_chonqingdaguan_reconciliation
from service.CynyHandle import process_chuyunnengyuan_reconciliation
from service.DgHandle import process_donguan_reconciliation
from service.DnHandle import process_dingnan_reconciliation
from service.FsqjHandle import process_foshangqiangjin_reconciliation
from service.FszlHandle import process_foshangzhonle_reconciliation
from service.GlHandle import process_gouling_reconciliation
from service.GydsHand import process_guanyindingsheng_reconciliation
from service.GzbHandle import process_gezhouba_reconciliation
from service.GzfqHandle import process_guizhoufuquan_reconciliation
from service.GzkyHandle import process_guizhoukeyu_reconciliation
from service.GzsrHandle import process_ganzhoushenrang_reconciliation
from service.HachHandle import process_huaianchuanhua_reconciliation
from service.HbhxHandle import process_hubeihuaxiang_reconciliation
from service.HbtfHandle import process_hubetuanfeng_reconciliation
from service.HbyjHandle import process_hebeyijiao_reconciliation, process_bazhoubei_reconciliation, \
    process_bazhounan_reconciliation, process_tangshang_reconciliation, process_dingzhou_reconciliation, \
    process_zhuozhounan_reconciliation, process_xushui_reconciliation
from service.HebhnHand import process_haoning_reconciliation
from service.HjxyHandel import process_hengjixinye_reconciliation
from service.HnsHandle import process_hanasi_reconciliation, process_hanasibei_reconciliation, \
    process_hanasinan_reconciliation
from service.HnsqHandle import process_henanshenqiu_reconciliation
from service.HrHand import process_xiashahanrang_reconciliation
from service.HyjyHandle import process_haiyoujieyan_reconciliation
from service.JhuazhonrangHandle import process_jinghuazhonron_reconciliation
from service.JhzrHandle import process_jinhuazhonrang_reconciliation
from service.JlccHandle import process_jilingchuncheng_reconciliation
from service.JrbHandle import process_jurengba_reconciliation
from service.JsmcHandle import process_jiansumeichun_reconciliation
from service.JsshHandle import process_jiansushihua_reconciliation
from service.JwxcHandle import process_jinweixingcheng_reconciliation
from service.JxgaHandle import process_jiangxigaoan_reconciliation
from service.JxgsHandle import process_jianxigaosu_reconciliation
from service.JxjtHandle import process_jiaxingjiatong_reconciliation
from service.JzzzHandle import process_jinzhouzhongzhen_reconciliation
from service.KgbdHandle import process_konggangbeidu_reconciliation
from service.LfatHandle import process_lanfananton_reconciliation
from service.LfxaHandle import process_lanfanxinao_reconciliation
from service.LhhnHandle import process_lanhehuineng_reconciliation
from service.LhzyHandle import process_luohezhongyu_reconciliation
from service.LwHandle import process_laiwu_reconciliation
from service.LyspHandle import process_lingyishengping_reconciliation
from service.LzhdHandle import process_lanzhouheding_reconciliation
from service.MqcHandle import process_meiqicheng_reconciliation
from service.NcwbHandle import process_nanchengwubo_reconciliation
from service.NxhsHandle import process_ninxiahensheng_reconciliation
from service.NxjcHandle import process_ninxiajincheng_reconciliation
from service.PsHandle import process_panshan_reconciliation
from service.QdchHandle import process_qingdaochanhai_reconciliation
from service.QdycHandle import process_qingdaoyonchang_reconciliation
from service.QsHandle import process_qushou_reconciliation
from service.SclxHandle import process_sichuanlixiang_reconciliation
from service.ShgsHandle import process_shihuaguanshi_reconciliation
from service.ShiLeHandle import process_shile_reconciliation
from service.ShlcHandle import process_shihualechang_reconciliation
from service.ShncHandle import process_shihuananchang_reconciliation
from service.ShtxHandle import process_shihuatenxian_reconciliation
from service.SjzlcHandle import process_shijiazhuanglaicheng_reconciliation
from service.SmxHandle import process_sanmengxia_reconciliation
from service.SxajHand import process_shangxianjie_reconciliation
from service.SxltdHandle import process_shanxilantiandong_reconciliation
from service.SxwyHandle import process_shangxiweiyang_reconciliation
from service.SydfHandle import process_shengyangdingfeng_reconciliation
from service.SylhHandle import process_shengyanliaohe_reconciliation
from service.SzhyHandle import process_shengzhenghaiyou_reconciliation
from service.SzldHandle import process_suzhoulvdao_reconciliation
from service.SzmjHandle import process_shengzhengmiaojia_reconciliation
from service.TjlnHandle import process_tianjinlvnen_reconciliation
from service.TjyhHandle import process_tianjinyinhai_reconciliation
from service.TyhyHandle import process_taiyuanhonyu_reconciliation
from service.TzsxHandle import process_taizhoushaungxin_reconciliation
from service.WaHandle import process_wengan_reconciliation
from service.WhhlsdHandle import process_wuhuhailianshida_reconciliation
from service.WhzrHandle import process_wuhuzhonrang_reconciliation
from service.XacsHandle import process_xianchuanshen_reconciliation
from service.XiayiHandle import process_xiayi_reconciliation
from service.XjhtHandle import process_xinjianghontong_reconciliation
from service.XjktHandle import process_xinjiangkaitong_reconciliation
from service.XxhgHandle import process_xianxianghuaxian_reconciliation
from service.XyHandle import process_xingyan_reconciliation
from service.XybHandle import process_xianyanbei_reconciliation
from service.YbHandle import process_yanbao_reconciliation
from service.ZhyhhHandle import process_zhonhaiyouhuihe_reconciliation
from service.ZhymHandle import process_zhonhaiyouming_reconciliation
from service.ZjtHandle import process_zhejiaotou_reconciliation
from service.ZrxlHandle import process_zhonrangxingle_reconciliation
from service.ZshHandle import process_zhonshihua_reconciliation
from service.ZyjnHandle import process_zhonyoujieneng_reconciliation
from service.ZyjyHandle import process_zhonyuanjiayou_reconciliation
from service.ZzHandle import process_zhengzhou_reconciliation
from utils.token import check_token_type

# logger = FlaskLogger.get_module_logger("SupplierReconciliationController.py")


# 创建蓝图
bp_reconciliation = Blueprint('reconciliation', __name__)
logger = FlaskLogger.get_module_logger("SupplierReconciliationController.py")

# 确保上传文件夹存在
upload_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../upload')
os.makedirs(upload_folder, exist_ok=True)

def allowed_file(filename):
    """
    判断文件是否允许上传
    """
    allowed_extensions = current_app.config.get('ALLOWED_EXTENSIONS', {'xls', 'xlsx'})
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions


bp_reconciliation = Blueprint('reconciliation', __name__)
@bp_reconciliation.route('/reconciliation', methods=['POST'])
def reconciliation_api():
    # 记录所有表单参数
    form_data = request.form.to_dict()
    logger.info(f"完整表单数据: {form_data}")

    # 记录请求头信息，包括可能的token
    headers = dict(request.headers)
    logger.info(f"请求头信息: {headers}")    # 检查文件部分

    # 获取 form-data 中的参数
    tokenStr = request.headers.get('Hstoken', type=str)
    type_param = request.headers.get('Type', type=int)

    # 验证 type 是否有效，如果提供了 type
    # if type_param is not None and type_param not in [2, 5, 9, 10, 11, 12, 13, 14]:
    #     return render_template('404.html')

    # 验证 token（无论 type 是否存在）
    # if tokenStr is None or tokenStr == '' or not check_token_type(type_param, tokenStr):
    #     return render_template("403.html")

    if 'file' not in request.files:
        logger.error("未上传文件")
        return jsonify({'error': '未上传文件'}), 400

    file = request.files['file']
    if file.filename == '':
        logger.error("未选择文件")
        return jsonify({'error': '未选择文件'}), 400

    if not allowed_file(file.filename):
        logger.error("文件格式错误")
        return jsonify({'error': '仅支持.xlsx和.xls文件'}), 400

    # 检查时间参数
    try:
        recon_start_time = request.form.get('start_time', '')
        recon_end_time = request.form.get('end_time', '')
        fault_tolerant = request.form.get('fault_tolerant') or None
        station_subject_id = request.form.get('station_subject_id') or None
        ignore_time = request.form.get('ignore_time') or None

        if not recon_start_time or not recon_end_time:
            logger.error("必须提供对账开始和结束时间")
            return jsonify({'error': '必须提供对账开始和结束时间'}), 400

        # 转换为datetime对象 (ISO格式: YYYY-MM-DDTHH:MM)
        # datetime-local控件生成的格式是 YYYY-MM-DDTHH:MM（不包含秒）
        try:
            # 转换时间（兼容两种格式）
            start_dt = datetime.fromisoformat(recon_start_time) if 'T' in recon_start_time else \
                datetime.strptime(recon_start_time, "%Y-%m-%d %H:%M:%S")
            end_dt = datetime.fromisoformat(recon_end_time) if 'T' in recon_end_time else \
                datetime.strptime(recon_end_time, "%Y-%m-%d %H:%M:%S")
        except ValueError:
            # 如果解析失败，尝试手动添加秒部分
            if len(recon_start_time) == 16:  # YYYY-MM-DDTHH:MM 格式
                recon_start_time += ":00"  # 添加 :00 秒
                recon_end_time += ":59"    # 添加 :00 秒
                start_dt = datetime.fromisoformat(recon_start_time)
                end_dt = datetime.fromisoformat(recon_end_time)
            else:
                raise ValueError("时间格式不正确")

        if start_dt >= end_dt:
            logger.error("结束时间必须晚于开始时间")
            return jsonify({'error': '结束时间必须晚于开始时间'}), 400
    except ValueError:
        return jsonify({'error': '时间格式不正确，请使用 YYYY-MM-DDTHH:MM 格式（例如：2025-06-01T00:00）'}), 400

    # 处理文件上传
    try:

        def sanitize_filename(filename):
            """保留中文、字母、数字和常用符号，过滤路径分隔符等危险字符"""
            # 允许的字符：中文、日韩文、字母、数字、空格、下划线、短横线、括号、感叹号等
            pattern = r'[^\w\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7a3\s_\-()（）！!.,#@]'
            safe_name = re.sub(pattern, '', filename)
            # 额外移除连续多个点（防止伪装扩展名）
            safe_name = re.sub(r'\.{2,}', '.', safe_name)
            return safe_name.strip()

        # 获取原始文件名
        original_filename = file.filename

        # 安全处理文件名（自动过滤非法字符）
        safe_filename = sanitize_filename(original_filename)  # 结果："6月赫森对账单（郑州）！.xlsx"

        # 分离文件名和扩展名（使用安全处理后的文件名）
        filename, ext = os.path.splitext(safe_filename)

        # 生成时间戳（格式示例：20240818_153045）
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

        # 构建最终文件名（使用安全处理后的文件名）
        final_filename = f"{filename}_{timestamp}{ext.lower()}"
        session['final_filename'] = final_filename

        # 生成日期分类目录（格式：YYYYMMDD）
        date_folder = datetime.now().strftime("%Y%m%d")

        # 创建目录（如果不存在）
        save_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../upload/' + date_folder)
        os.makedirs(save_dir, exist_ok=True)

        # 完整存储路径
        file_path = os.path.join(save_dir, final_filename)

        # 保存文件
        file.save(file_path)

        # 处理对账逻辑
        result = process_reconciliation(recon_start_time, recon_end_time, file_path, filename, fault_tolerant, station_subject_id, ignore_time)

        query = {
            "开始时间": recon_start_time,
            "结束时间": recon_end_time,
            "容错公斤数": float(fault_tolerant) if fault_tolerant is not None else 0.0,
            "忽略时间": bool(ignore_time)
        }

        # 记录日志
        log_file_reconciliation(
            operation_type="上传文件对比",
            user_id=session.get('user_id'),
            user_name=session.get('real_name'),
            file_name=final_filename,
            data=result,
            query=query
        )

        return jsonify(result)

    except Exception as e:
        logger.error(
            "处理对账时出错: %s",  # 使用 %s 避免 f-string 潜在问题
            str(e),
            exc_info=True  # 仍然需要显式开启堆栈
        )
        # 检查异常信息是否包含特定内容
        error_message = str(e)
        if "Excel文件与选择的气站主体不一致" in error_message:
            return jsonify({'error': error_message}), 500
        else:
            return jsonify({'error': 'Excel格式有误，请联系技术部！'}), 500

@bp_reconciliation.route('/logRecording', methods=['POST'])
def log_recording():
    user_name = session.get('real_name')
    user_id = session.get('user_id')
    final_filename = session.get('final_filename')
    operation_type = request.form.get('operation_type') or None
    data_str = request.form.get('data')  # 从表单获取 JSON 字符串
    data_dict = None

    if data_str:
        try:
            data_dict = json.loads(data_str)  # 转换为 Python 字典
        except json.JSONDecodeError as e:
            # 如果前端传的不是合法 JSON，可以记录日志或返回错误
            print(f"JSON 解析失败: {e}")
            data_dict = {"raw_data": data_str}  # 可保留原始字符串

    # 调用日志函数
    log_file_reconciliation(
        operation_type=operation_type,
        user_id=user_id,
        user_name=user_name,
        file_name=final_filename,
        data=None,
        query=data_dict
    )
    return jsonify(code=200, msg='操作成功')



def process_reconciliation(start_time, end_time, file_path, filename, fault_tolerant, station_id, ignore_time):
    """
    根据文件名路由到不同的处理函数
    规则：
    1. 文件名中包含地区关键词即匹配（不区分大小写）
    2. 支持多个地区关键词匹配
    3. 支持优先级匹配（如同时包含"安阳"和"郑州"时优先用安阳）
    """

    import re

    # 地区处理函数映射表（简化，仅包含安阳）
    region_handlers = [
        (["安阳"], process_anyang_reconciliation),
        (["滨州"], process_binzhou_reconciliation),
        (["东莞新锋"], process_donguan_reconciliation),
        (["葛洲坝", "利鑫能源"], process_gezhouba_reconciliation),
        (["贵州科宇"], process_guizhoukeyu_reconciliation),
        (["湖北华祥"], process_hubeihuaxiang_reconciliation),
        (["天津银海"], process_tianjinyinhai_reconciliation),
        (["咸阳北"], process_xianyanbei_reconciliation),
        (["信阳"], process_xingyan_reconciliation),
        (["成都简阳"], process_chengdujianyang_reconciliation),
        (["重庆锦润大观"], process_chonqingdaguan_reconciliation),
        (["楚云能源"], process_chuyunnengyuan_reconciliation),
        (["包头"], process_baotoushixin_reconciliation),
        (["佛山中乐"], process_foshangzhonle_reconciliation),
        (["贵州福泉"], process_guizhoufuquan_reconciliation),
        (["哈纳斯"], process_hanasi_reconciliation),
        (["哈纳斯镇平-北"], process_hanasibei_reconciliation),
        (["哈纳斯镇平-南"], process_hanasinan_reconciliation),
        (["揭阳"], process_haiyoujieyan_reconciliation),
        (["河北冀交"], process_hebeyijiao_reconciliation),
        (["霸州北"], process_bazhoubei_reconciliation),
        (["霸州南"], process_bazhounan_reconciliation),
        (["唐山"], process_tangshang_reconciliation),
        (["定州"], process_dingzhou_reconciliation),
        (["涿州南"], process_zhuozhounan_reconciliation),
        (["徐水"], process_xushui_reconciliation),
        (["沈丘"], process_henanshenqiu_reconciliation),
        (["夏邑"], process_xiayi_reconciliation),
        (["恒基新野"], process_hengjixinye_reconciliation),
        (["淮安"], process_huaianchuanhua_reconciliation),
        (["吉林春城"], process_jilingchuncheng_reconciliation),
        (["嘉兴嘉通", "嘉通"], process_jiaxingjiatong_reconciliation),
        (["江苏梅村"], process_jiansumeichun_reconciliation),
        (["江西高安"], process_jiangxigaoan_reconciliation),
        (["莱芜"], process_laiwu_reconciliation),
        (["漯河中裕"], process_luohezhongyu_reconciliation),
        (["南城物博"], process_nanchengwubo_reconciliation),
        (["盘锦誉辉"], process_panshan_reconciliation),
        (["青岛昌海"], process_qingdaochanhai_reconciliation),
        (["青岛永昌"], process_qingdaoyonchang_reconciliation),
        (["渠首"], process_qushou_reconciliation),
        (["三门峡"], process_sanmengxia_reconciliation),
        (["山西安洁"], process_shangxianjie_reconciliation),
        (["莱辰"], process_shijiazhuanglaicheng_reconciliation),
        (["四川荔乡"], process_sichuanlixiang_reconciliation),
        (["苏州绿岛"], process_suzhoulvdao_reconciliation),
        (["天津绿能"], process_tianjinlvnen_reconciliation),
        (["芜湖石大"], process_wuhuhailianshida_reconciliation),
        (["芜湖中燃"], process_wuhuzhonrang_reconciliation),
        (["西安创盛"], process_xianchuanshen_reconciliation),
        (["新疆洪通"], process_xinjianghontong_reconciliation),
        (["沈阳辽河"], process_shengyanliaohe_reconciliation),
        (["新乐"], process_zhonrangxingle_reconciliation),
        (["石化回河"], process_zhonshihua_reconciliation),
        (["中油洁能"], process_zhonyoujieneng_reconciliation),
        (["安徽双合"], process_anhuishuanghe_reconciliation),
        (["郑州"], process_zhengzhou_reconciliation),
        (["成都双瑞"], process_chendushuangrui_reconciliation),
        (["定南"], process_dingnan_reconciliation),
        (["赣州深燃"], process_ganzhoushenrang_reconciliation),
        (["构林"], process_gouling_reconciliation),
        (["冠英鼎胜"], process_guanyindingsheng_reconciliation),
        (["浩宁"], process_haoning_reconciliation),
        (["下沙杭燃"], process_xiashahanrang_reconciliation),
        (["湖北团风"], process_hubetuanfeng_reconciliation),
        (["江苏石化"], process_jiansushihua_reconciliation),
        (["江西高速"], process_jianxigaosu_reconciliation),
        (["锦州中正"], process_jinzhouzhongzhen_reconciliation),
        (["举人坝"], process_jurengba_reconciliation),
        (["兰州和定"], process_lanzhouheding_reconciliation),
        (["廊坊安通"], process_lanfananton_reconciliation),
        (["廊坊新奥"], process_lanfanxinao_reconciliation),
        (["联合汇能"], process_lanhehuineng_reconciliation),
        (["临沂盛平"], process_lingyishengping_reconciliation),
        (["南昌"], process_shihuananchang_reconciliation),
        (["宁夏恒盛"], process_ninxiahensheng_reconciliation),
        (["陕西未央"], process_shangxiweiyang_reconciliation),
        (["深圳秒加"], process_shengzhengmiaojia_reconciliation),
        (["沈阳顶峰"], process_shengyangdingfeng_reconciliation),
        (["世乐"], process_shile_reconciliation),
        (["泰州双新"], process_taizhoushaungxin_reconciliation),
        (["瓮安"], process_wengan_reconciliation),
        (["献县华港"], process_xianxianghuaxian_reconciliation),
        (["燕宝"], process_yanbao_reconciliation),
        (["长春英泰"], process_changchunyintai_reconciliation),
        (["中源佳油"], process_zhonyuanjiayou_reconciliation),
        (["中海油回河"], process_zhonhaiyouhuihe_reconciliation),
        (["中海油闽"], process_zhonhaiyouming_reconciliation),
        (["安徽肥东"], process_anhuifeidon_reconciliation),
        (["安徽红星"], process_anhuihonxing_reconciliation),
        (["安徽罗集"], process_anhuiluoji_reconciliation),
        (["佛山强劲"], process_foshangqiangjin_reconciliation),
        (["金华中燃"], process_jinghuazhonron_reconciliation),
        (["泾渭新城"], process_jinweixingcheng_reconciliation),
        (["空港北杜", "空港"], process_konggangbeidu_reconciliation),
        (["美旗城"], process_meiqicheng_reconciliation),
        (["宁夏精诚"], process_ninxiajincheng_reconciliation),
        (["陕西蓝田东"], process_shanxilantiandong_reconciliation),
        (["深圳海油"], process_shengzhenghaiyou_reconciliation),
        (["石化广石"], process_shihuaguanshi_reconciliation),
        (["石化乐昌"], process_shihualechang_reconciliation),
        (["石化藤县"], process_shihuatenxian_reconciliation),
        (["太原宏宇"], process_taiyuanhonyu_reconciliation),
        (["新疆凯通"], process_xinjiangkaitong_reconciliation),
        (["浙交投"], process_zhejiaotou_reconciliation),
    ]

    matched_handler = None

    # 第一轮：精准匹配（完全一致，立即返回）
    for keywords, handler in region_handlers:
        if filename in keywords:
            matched_handler = handler
            break

    # 第二轮：模糊匹配（只有在精准匹配失败时才执行）
    if not matched_handler:
        max_len = 0
        for keywords, handler in region_handlers:
            for keyword in keywords:
                if re.search(f".*{re.escape(keyword)}.*", filename, re.IGNORECASE):
                    if len(keyword) > max_len:  # 匹配长度优先
                        matched_handler = handler
                        max_len = len(keyword)

    if not matched_handler:
        # 提取所有可能的关键词（展开数组）
        possible_regions = [kw for keywords, _ in region_handlers for kw in keywords]
        raise ValueError(
            f"无法识别文件所属地区。文件名中应包含以下地区关键词之一: {', '.join(possible_regions)}。"
            f"当前文件名: {filename}"
        )

    # 调用匹配的处理函数
    return matched_handler(start_time, end_time, file_path, fault_tolerant, station_id, ignore_time)








